package com.k2data.k2app.service;

import com.google.common.base.Splitter;
import com.k2data.app.kmx.KmxClient;
import com.k2data.app.kmx.cond.AssetsV2Builder;
import com.k2data.app.kmx.cond.KmxCond;
import com.k2data.app.kmx.domain.StreamRule;
import com.k2data.k2app.common.KmxParams;
import com.k2data.k2app.common.MyConstant;
import com.k2data.k2app.domain.po.MonitorLimitValue;
import com.k2data.k2app.domain.po.RDeviceMonitorPoint;
import com.k2data.k2app.domain.po.RDeviceMonitorPointCopy;
import com.k2data.k2app.domain.po.TMonitorLimitValue;
import com.k2data.k2app.mapper.MonitorLimitValueMapper;
import com.k2data.k2app.mapper.RDeviceMonitorPointCopyMapper;
import com.k2data.k2app.mapper.RDeviceMonitorPointMapper;
import com.k2data.k2app.mapper.TMonitorLimitValueMapper;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author lidong9144@163.com 17-7-13.
 */
@Log4j2
@Service
public class KmxRuleService {

    private final TMonitorLimitValueMapper tMonitorLimitValueMapper;
    private final KmxParams kmxParams;
    private final RDeviceMonitorPointMapper rDeviceMonitorPointMapper;

    @Autowired
    private RDeviceMonitorPointCopyMapper rDeviceMonitorPointCopyMapper;
    @Autowired
    private MonitorLimitValueMapper monitorLimitValueMapper;

    @Autowired
    public KmxRuleService(TMonitorLimitValueMapper tMonitorLimitValueMapper, KmxParams kmxParams,
                          RDeviceMonitorPointMapper rDeviceMonitorPointMapper) {
        this.tMonitorLimitValueMapper = tMonitorLimitValueMapper;
        this.kmxParams = kmxParams;
        this.rDeviceMonitorPointMapper = rDeviceMonitorPointMapper;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void pushLimitValue(TMonitorLimitValue limit) {
        TMonitorLimitValue tMonitorLimitValue = new TMonitorLimitValue();
        tMonitorLimitValue.setId(limit.getId());
        tMonitorLimitValue.setState(1);
        tMonitorLimitValueMapper.updateByPrimaryKeySelective(tMonitorLimitValue);

        Integer level = 1;
        String operator = "";
        if ("ggt".equals(limit.getRule())) {
            level = 2;
            operator = "lt";
        }
        if ("gle".equals(limit.getRule())) {
            level = 2;
            operator = "ge";
        }
        if ("gt".equals(limit.getRule())) {
            level = 1;
            operator = "lt";
        }
        if ("le".equals(limit.getRule())) {
            level = 1;
            operator = "ge";
        }

        String[] ids = limit.getSensorNameEn().split("_");
        String id = ids[0]+"_"+ids[1];
        KmxCond limitCond = KmxCond.streamRule(kmxParams.getKmxInitParams())
                .post()
                .fieldGroupId(id)
                .fieldId(limit.getKmxVariableNameEn())
                .level(level)
                .operator(operator)
                .value(limit.getValue().toString())
                .description(limit.getName())
                .build();

        KmxClient.sync(limitCond);
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void pushLimit(Long id) {
        RDeviceMonitorPoint rDeviceMonitorPoint = rDeviceMonitorPointMapper.selectLimit(id);

        if (rDeviceMonitorPoint == null) {
            return;
        }

        List<String> ids = Splitter.on("_")
                .splitToList(rDeviceMonitorPoint.getDeviceNo());

        Map<String, Object> compoundId = new HashMap<String, Object>();
        compoundId.put(MyConstant.KMX_ID_FIELD_FACTORY_NAME, ids.get(0));
        compoundId.put(MyConstant.KMX_ID_FIELD_EQUIPMENT_NAME, ids.get(1));
        compoundId.put(MyConstant.KMX_ID_FIELD_MACHINE_NAME, ids.get(2));
        compoundId.put(MyConstant.KMX_ID_FIELD_CHANNEL_ID, rDeviceMonitorPoint.getChannelId());
        compoundId.put(MyConstant.KMX_ID_FIELD_DATA_TYPE, "1");
        compoundId.put(MyConstant.KMX_ID_FIELD_CHANNEL_TYPE, "0");

        RDeviceMonitorPoint updateObj = new RDeviceMonitorPoint();

        if (rDeviceMonitorPoint.getGtLimit() != null) {
            if (rDeviceMonitorPoint.getGtRuleId() != null) {
                put(rDeviceMonitorPoint.getGtRuleId(),
                        rDeviceMonitorPoint.getNameEn(),
                        1,
                        "lt",
                        rDeviceMonitorPoint.getGtLimit().toString(),
                        compoundId,rDeviceMonitorPoint.getMonitorPointId());
            } else {
                Long gtRuleId = post(rDeviceMonitorPoint.getNameEn(),
                        1,
                        "lt",
                        rDeviceMonitorPoint.getGtLimit().toString(),
                        compoundId);

                updateObj.setGtRuleId(gtRuleId);
            }
        }

        if (rDeviceMonitorPoint.getGgtLimit() != null) {
            if (rDeviceMonitorPoint.getGgtRuleId() != null) {
                put(rDeviceMonitorPoint.getGgtRuleId(),
                        rDeviceMonitorPoint.getNameEn(),
                        2,
                        "lt",
                        rDeviceMonitorPoint.getGgtLimit().toString(),
                        compoundId,rDeviceMonitorPoint.getMonitorPointId());
            } else {
                Long ggtRuleId = post(rDeviceMonitorPoint.getNameEn(),
                        2,
                        "lt",
                        rDeviceMonitorPoint.getGgtLimit().toString(),
                        compoundId);

                updateObj.setGgtRuleId(ggtRuleId);
            }
        }

        if (rDeviceMonitorPoint.getLtLimit() != null) {
            if (rDeviceMonitorPoint.getLtRuleId() != null) {
                put(rDeviceMonitorPoint.getLtRuleId(),
                        rDeviceMonitorPoint.getNameEn(),
                        1,
                        "ge",
                        rDeviceMonitorPoint.getLtLimit().toString(),
                        compoundId,rDeviceMonitorPoint.getMonitorPointId());
            } else {
                Long ltRuleId = post(rDeviceMonitorPoint.getNameEn(),
                        1,
                        "ge",
                        rDeviceMonitorPoint.getLtLimit().toString(),
                        compoundId);

                updateObj.setLtRuleId(ltRuleId);
            }
        }

        if (rDeviceMonitorPoint.getGltLimit() != null) {
            if (rDeviceMonitorPoint.getGltRuleId() != null) {
                put(rDeviceMonitorPoint.getGltRuleId(),
                        rDeviceMonitorPoint.getNameEn(),
                        2,
                        "ge",
                        rDeviceMonitorPoint.getGltLimit().toString(),
                        compoundId,
                        rDeviceMonitorPoint.getMonitorPointId());
            } else {
                Long gltRuleId = post(rDeviceMonitorPoint.getNameEn(),
                        2,
                        "ge",
                        rDeviceMonitorPoint.getGltLimit().toString(),
                        compoundId);

                updateObj.setGltRuleId(gltRuleId);
            }
        }

        updateObj.setId(id);
        updateObj.setState(1);
        rDeviceMonitorPointMapper.updateByPrimaryKeySelective(updateObj);
    }


    /**
     * 同步设备测点阈值
     *
     * gt：大于，对应value必须是数值型字符串（如“123”，“-12.34”等），支持小数和负数；
       lt：小于，value要求同gt；
       eq：等于，value要求同gt；
       ge：大于等于，value要求同gt；
       le：小于等于，value要求同gt；
       ne：等于，value要求同gt；
       in：属于，value格式为 "{aaa, 123, -12.34}"，表示 fieldValue.toString()等于"aaa"(区分大小写) or “123” or “-12.34”；
       range：区间，value格式为 "(0, 100]" 或 “(0, 20) (40, 60)” 或 "(,100) (200,)"，支持开闭区间、多区间、正负无穷区间。
     * @param id
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void pushLimitCopy(Long id) {
        RDeviceMonitorPointCopy rDeviceMonitorPoint = rDeviceMonitorPointCopyMapper.selectLimitByPoint(id);

        if (rDeviceMonitorPoint == null) {
            return;
        }

        List<String> ids = Splitter.on("_")
                .splitToList(rDeviceMonitorPoint.getDeviceNo());

        Map<String, Object> compoundId = new HashMap<String, Object>();
        compoundId.put(MyConstant.KMX_ID_FIELD_FACTORY_NAME, ids.get(0));
        compoundId.put(MyConstant.KMX_ID_FIELD_EQUIPMENT_NAME, ids.get(1));
        compoundId.put(MyConstant.KMX_ID_FIELD_MACHINE_NAME, ids.get(2));
        compoundId.put(MyConstant.KMX_ID_FIELD_CHANNEL_ID, rDeviceMonitorPoint.getChannelId());
        compoundId.put(MyConstant.KMX_ID_FIELD_DATA_TYPE, "1");
        if(rDeviceMonitorPoint.getNameEn().equals("c_sta")){
            compoundId.put(MyConstant.KMX_ID_FIELD_CHANNEL_TYPE, "1");
        }else if(rDeviceMonitorPoint.getNameEn().equals("c_vib")){
            compoundId.put(MyConstant.KMX_ID_FIELD_CHANNEL_TYPE, "0");
        }else if(rDeviceMonitorPoint.getNameEn().equals("c_oil_sensor")){
            compoundId.put(MyConstant.KMX_ID_FIELD_CHANNEL_TYPE, "4");
        }

        List<MonitorLimitValue> monitorLimitValues = rDeviceMonitorPoint.getMonitorLimitValues();
        if(monitorLimitValues !=null && monitorLimitValues .size()>0){
            for(MonitorLimitValue monitorLimitValue:monitorLimitValues){
                String rule = monitorLimitValue.getRule();
                String kmxRule = "";
                switch (rule) {
                    case "lt":
//                        kmxRule = "lt";
                        kmxRule = "le";
                        break;
                    case "glt":
//                        kmxRule = "lt";
                        kmxRule = "le";
                        break;
                    case "gt":
//                        kmxRule = "gt";
                        kmxRule = "ge";
                        break;
                    case "ggt":
//                        kmxRule = "gt";
                        kmxRule = "ge";
                        break;
                    default:
                        break;
                }
                if(monitorLimitValue.getState() != null && monitorLimitValue.getState() == 1 && monitorLimitValue.getRule() != null){
                    // 已经同步到kmx的规则，进行更新操作
                    if(monitorLimitValue.getDeleteFlag()==null || monitorLimitValue.getDeleteFlag().equals(0)){
                        //每删除的进行更新
                        putCopy(monitorLimitValue.getKmxRuleId(),
                                rDeviceMonitorPoint.getNameEn(),
                                monitorLimitValue.getLevel(),
                                kmxRule,
                                monitorLimitValue.getValue().toString(),
                                compoundId,
                                monitorLimitValue.getKmxVariableNameEn());
                        //更新同步状态
                        monitorLimitValue.setState(1);
                        monitorLimitValueMapper.updateByPrimaryKeySelective(monitorLimitValue);
                        //更新同步状态
                        RDeviceMonitorPointCopy rDeviceMonitorPointCopy1 = new RDeviceMonitorPointCopy();
                        rDeviceMonitorPointCopy1.setState(1);
                        rDeviceMonitorPointCopy1.setId(id);
                        rDeviceMonitorPointCopyMapper.updateByPrimaryKeySelective(rDeviceMonitorPointCopy1);
                    }else{
                        //删除掉的进行删除
                        delete(monitorLimitValue.getKmxRuleId());
                        monitorLimitValueMapper.deleteByPrimaryKey(monitorLimitValue.getId());
                    }
                } else {
                    if(monitorLimitValue.getDeleteFlag()==null || monitorLimitValue.getDeleteFlag().equals(0)){
                        try {
                            addAsset(compoundId,rDeviceMonitorPoint.getNameEn());
                        } catch (Exception e) {
                            log.debug("asset 已经注册过了");
                        }finally {
                            // 没有同步到kmx的规则，进行增加操作
                            Long gtRuleId = postCopy(rDeviceMonitorPoint.getNameEn(),
                                    monitorLimitValue.getLevel(),
                                    kmxRule,
                                    monitorLimitValue.getValue().toString(),
                                    compoundId,monitorLimitValue.getKmxVariableNameEn());
                            monitorLimitValue.setKmxRuleId(gtRuleId);

                            //更新同步状态
                            monitorLimitValue.setState(1);
                            monitorLimitValueMapper.updateByPrimaryKeySelective(monitorLimitValue);

                            //更新同步状态
                            RDeviceMonitorPointCopy rDeviceMonitorPointCopy1 = new RDeviceMonitorPointCopy();
                            rDeviceMonitorPointCopy1.setState(1);
                            rDeviceMonitorPointCopy1.setId(id);
                            rDeviceMonitorPointCopyMapper.updateByPrimaryKeySelective(rDeviceMonitorPointCopy1);
                        }
                    }else{
                        //删除掉的还没同步的进行删除
                        monitorLimitValueMapper.deleteByPrimaryKey(monitorLimitValue.getId());
                    }
                }
                }
        }
    }

    /**
     * 同步单个阈值
     * @param monitorLimitValue 阈值
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void pushLimitOne(MonitorLimitValue monitorLimitValue) {
        RDeviceMonitorPointCopy rDeviceMonitorPoint = rDeviceMonitorPointCopyMapper.selectLimitByLimitId(monitorLimitValue.getId());
        if (rDeviceMonitorPoint == null) {
            return;
        }
        List<String> ids = Splitter.on("_")
                .splitToList(rDeviceMonitorPoint.getDeviceNo());

        Map<String, Object> compoundId = new HashMap<String, Object>();
        compoundId.put(MyConstant.KMX_ID_FIELD_FACTORY_NAME, ids.get(0));
        compoundId.put(MyConstant.KMX_ID_FIELD_EQUIPMENT_NAME, ids.get(1));
        compoundId.put(MyConstant.KMX_ID_FIELD_MACHINE_NAME, ids.get(2));
        compoundId.put(MyConstant.KMX_ID_FIELD_CHANNEL_ID, rDeviceMonitorPoint.getChannelId());
        compoundId.put(MyConstant.KMX_ID_FIELD_DATA_TYPE, "1");
        compoundId.put(MyConstant.KMX_ID_FIELD_CHANNEL_TYPE, "0");
        System.out.println("compoundIdStr:");
        System.out.println(compoundId.toString());

        String rule = monitorLimitValue.getRule();
        String kmxRule = "";
        switch (rule) {
            case "lt":
//                        kmxRule = "lt";
                kmxRule = "le";
                break;
            case "glt":
//                        kmxRule = "lt";
                kmxRule = "le";
                break;
            case "gt":
//                        kmxRule = "gt";
                kmxRule = "ge";
                break;
            case "ggt":
//                        kmxRule = "gt";
                kmxRule = "ge";
                break;
            default:
                break;
        }

        if(monitorLimitValue.getState() != null && monitorLimitValue.getState() == 1 && monitorLimitValue.getRule() != null){
            // 已经同步到kmx的规则，进行更新操作
            if(monitorLimitValue.getDeleteFlag()==null || monitorLimitValue.getDeleteFlag().equals(0)){
                //每删除的进行更新
                putCopy(monitorLimitValue.getKmxRuleId(),
                        rDeviceMonitorPoint.getNameEn(),
                        monitorLimitValue.getLevel(),
                        kmxRule,
                        monitorLimitValue.getValue().toString(),
                        compoundId,
                        monitorLimitValue.getKmxVariableNameEn());
            }else{
                //删除掉的进行删除
                delete(monitorLimitValue.getKmxRuleId());
                monitorLimitValueMapper.deleteByPrimaryKey(monitorLimitValue.getId());
            }
        } else {
            if(monitorLimitValue.getDeleteFlag()==null || monitorLimitValue.getDeleteFlag().equals(0)){
                // 没有同步到kmx的规则，进行增加操作
                Long gtRuleId = postCopy(rDeviceMonitorPoint.getNameEn(),
                        monitorLimitValue.getLevel(),
                        kmxRule,
                        monitorLimitValue.getValue().toString(),
                        compoundId,monitorLimitValue.getKmxVariableNameEn());
                monitorLimitValue.setKmxRuleId(gtRuleId);

                //更新同步状态
                monitorLimitValue.setState(1);
                monitorLimitValueMapper.updateByPrimaryKeySelective(monitorLimitValue);

                //更新同步状态
                RDeviceMonitorPointCopy rDeviceMonitorPointCopy1 = new RDeviceMonitorPointCopy();
                rDeviceMonitorPointCopy1.setState(1);
                rDeviceMonitorPointCopy1.setId(monitorLimitValue.getId());
                rDeviceMonitorPointCopyMapper.updateByPrimaryKeySelective(rDeviceMonitorPointCopy1);
            }else{
                //删除掉的还没同步的进行删除
                monitorLimitValueMapper.deleteByPrimaryKey(monitorLimitValue.getId());
            }
        }
    }

    private Long post(String fieldGroupId, int level, String operator, String value,
                      Map<String, Object> compoundId) {
        String fieldId = "";
        if("c_vib".equals(fieldGroupId)){
            fieldId = "direc";
        }else{
            fieldId = "value";
        }
        KmxCond limitCond = KmxCond.streamRule(kmxParams.getKmxInitParams())
                .post()
                .fieldGroupId(fieldGroupId)
                .fieldId(fieldId)
                .compoundId(compoundId)
                .level(level)
                .operator(operator)
                .value(value)
                .build();

        StreamRule streamRule = KmxClient.sync(limitCond);
        return streamRule.getDataRule().getId();
    }

    /**
     * 添加预警规则
     * @param fieldGroupId
     * @param level
     * @param operator
     * @param value
     * @param compoundId
     * @param fieldId
     * @return
     */
    private Long postCopy(String fieldGroupId, int level, String operator, String value,
                      Map<String, Object> compoundId, String fieldId) {
        KmxCond limitCond = KmxCond.streamRule(kmxParams.getKmxInitParams())
                .post()
                .fieldGroupId(fieldGroupId)
                .fieldId(fieldId)
                .compoundId(compoundId)
                .level(level)
                .operator(operator)
                .value(value)
                .build();

        StreamRule streamRule = KmxClient.sync(limitCond);
        return streamRule.getDataRule().getId();
    }

    private void put(Long id, String fieldGroupId, int level, String operator, String value,
                     Map<String, Object> compoundId,Long pointId) {
        String fieldId = "";
        if("c_vib".equals(fieldGroupId)){
            fieldId = "direc";
        } else {
            fieldId = "value";
        }
        KmxCond limitCond = KmxCond.streamRule(kmxParams.getKmxInitParams())
                .put()
                .id(id)
                .fieldGroupId(fieldGroupId)
                .fieldId(fieldId)
                .compoundId(compoundId)
                .level(level)
                .operator(operator)
                .value(value)
                .build();

        KmxClient.sync(limitCond);
    }


    /**
     *
     * 更新预警规则
     * @param id
     * @param fieldGroupId
     * @param level
     * @param operator
     * @param value
     * @param compoundId
     */
    private void putCopy(Long id, String fieldGroupId, int level, String operator, String value,
                     Map<String, Object> compoundId,String fieldId) {
        KmxCond limitCond = KmxCond.streamRule(kmxParams.getKmxInitParams())
                .put()
                .id(id)
                .fieldGroupId(fieldGroupId)
                .fieldId(fieldId)
                .compoundId(compoundId)
                .level(level)
                .operator(operator)
                .value(value)
                .build();

        KmxClient.sync(limitCond);
    }

    /**
     * 删除预警规则
     *
     * @param id
     */
    private void delete(Long id){
        KmxCond build = KmxCond.streamRule(kmxParams.getKmxInitParams())
                .delete()
                .id(id)
                .build();
        KmxClient.sync(build);
    }


    /**
     * 临时接口
     *
     * 同步重新导入的测点
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void pushDifferentPoint() {
        List<RDeviceMonitorPointCopy> rDeviceMonitorPoint = rDeviceMonitorPointCopyMapper.selectDiffertPoint();
        for (int i = 0; i < rDeviceMonitorPoint.size(); i++) {
            pushLimitCopy(rDeviceMonitorPoint.get(i).getId());
        }
    }


    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void addAsset( Map<String, Object> compoundIds,String fieldGroup) throws InterruptedException{
        String assetName="";
        AssetsV2Builder.PostBuilder postBuilder = KmxCond.assets(kmxParams.getKmxInitParams()).post().fieldGroupId(fieldGroup);
        compoundIds.forEach((k,v)->{
            postBuilder.addCompoundId(k,v.toString());
        });
        KmxCond build = postBuilder.description(assetName).name(assetName).build();
        KmxClient.sync(build);
    }
}
